package com.dean.batch.service;

import com.dean.batch.entity.SysBatchJob;
import com.dean.batch.entity.SysBatchJobDepend;
import com.dean.batch.service.impl.BatchImpl1;
import com.dean.batch.service.impl.BatchImpl2;
import com.dean.batch.service.impl.BatchImpl3;
import com.dean.batch.service.impl.BatchImpl4;
import com.dean.service.DeanExecutorService;
import com.dean.ui.panel.DeanPanel;
import com.dean.utils.DeanJdbcUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName DeanBatchJobExecuter
 * @Description dean任务执行器
 * @Author dean
 * @Date 2021/12/16 12:01
 */
public class DeanBatchJobExecuter implements Runnable {
    public final static String WAITTING = "WAITTING";
    public final static String RUNNING = "RUNNING";
    public final static String SUCCESS = "SUCCESS";
    private final static Logger logger = LoggerFactory.getLogger(DeanBatchJobExecuter.class);
    private String jobId;
    // WAITTING RUNNING SUCCESS
    private ConcurrentHashMap<String,String> jobRunStatus;

    public DeanBatchJobExecuter(String jobId, ConcurrentHashMap<String, String> jobRunStatus) {
        this.jobId = jobId;
        this.jobRunStatus = jobRunStatus;
    }

    private DeanBatchJobExecuter() {
    }

    private void execute(String jobId, ConcurrentHashMap<String,String> jobRunStatus) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        SysBatchJob sysBatchJob = getDeanBatchJob(jobId);
        // DeanJdbcUtils.execute("update sys_batch_job set job_status = ? where  job_id = ? ",jobId,RUNNING);
        // 当前任务状态分析 双重锁检查当前任务状态
        // SysBatchJob jobStatus = getDeanBatchJob(jobId);
        if(RUNNING.equals(jobRunStatus.get(jobId))){
            logger.debug("当前任务[{}]已在执行中,不再重复执行",jobId);
            return;
        }
        // 如果当前任务已经执行成功了 则不在执行
        if(SUCCESS.equals(jobRunStatus.get(jobId))){
            logger.debug("当前任务[{}]已经执行完成,不再重复执行",jobId);
            return;
        }
        synchronized (jobRunStatus){
            if(RUNNING.equals(jobRunStatus.get(jobId))){
                logger.debug("当前任务[{}]已在执行中,不再重复执行",jobId);
                return;
            }
            // 如果当前任务已经执行成功了 则不在执行
            if(SUCCESS.equals(jobRunStatus.get(jobId))){
                logger.debug("当前任务[{}]已经执行完成,不再重复执行",jobId);
                return;
            }
        }


        // 获取上游依赖 检查
        List<SysBatchJobDepend> upDepends = getUpDepend(jobId);
        if(upDepends != null && !upDepends.isEmpty()){
            for (SysBatchJobDepend upDepend : upDepends) {
                if(!SUCCESS.equals(jobRunStatus.get(upDepend.getDependJobId()))){
                    logger.debug("当前任务[{}]依赖的任务[{}]暂未执行完成",jobId,upDepend.getDependJobId());
                    return;
                }
            }
        }
        jobRunStatus.put(jobId,RUNNING);
        DeanBatchJobService deanBatchJobService = (DeanBatchJobService) Class.forName(sysBatchJob.getJobClass()).newInstance();
        deanBatchJobService.execute(sysBatchJob);
       // DeanJdbcUtils.execute("update sys_batch_job set job_status = ? where  job_id = ? ",jobId,SUCCESS);
        jobRunStatus.put(jobId,SUCCESS);
        logger.info("任务【{}】执行完成",jobId);
        // 获取下游依赖
        List<SysBatchJobDepend> unDepends = getDownDepend(jobId);
        // 执行任务通知 检查下游节点
        for (SysBatchJobDepend unDepend : unDepends) {
            String unDependJobId = unDepend.getDependJobId();
            DeanExecutorService.getInstance().execute(new DeanBatchJobExecuter(unDependJobId,jobRunStatus));
        }
    }

    private SysBatchJob getDeanBatchJob(String jobId){
        SysBatchJob batchJob = null;
        String sql = "select * from sys_batch_job where job_id = ?";
        batchJob = new DeanJdbcUtils<SysBatchJob>().queryForObject(sql,SysBatchJob.class,jobId);
        return batchJob;
    }

    /**
     * 获取上游依赖
     * @param jobId
     * @return
     */
    private List<SysBatchJobDepend> getUpDepend(String jobId){
        List<SysBatchJobDepend> depends = getDepend(jobId,"UP");
        return depends;
    }

    /**
     * 获取下游依赖
     * @param jobId
     * @return
     */
    private List<SysBatchJobDepend> getDownDepend(String jobId){
        List<SysBatchJobDepend> depends = getDepend(jobId,"DOWN");
        return depends;
    }

    private List<SysBatchJobDepend> getDepend(String jobId,String jobType){
        String sql = "select * from sys_batch_job_depend where job_id = ? and depend_type=?";
        List<SysBatchJobDepend> depends = new DeanJdbcUtils<SysBatchJobDepend>().queryForList(sql,SysBatchJobDepend.class,jobId,jobType);
        if(depends == null || depends.isEmpty()){
            return new ArrayList<SysBatchJobDepend>();
        }
        return depends;
    }

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        try {
            this.execute(jobId, jobRunStatus);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
